package pwd.allen.util.mock.mvc;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import pwd.allen.service.MyService;
import pwd.allen.web.controller.MyController;
import pwd.allen.web.converter.StringToDateConverter;
import pwd.allen.web.controlleradvice.MyExceptionHandler;
import pwd.allen.web.filter.MyFilter;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

/**
 * 手动模拟方式
 *
 * 初始化mock（能解析@Mock @injectMock等标签）的两种方式：
 *  1.测试类加上注解：@RunWith(MockitoJUnitRunner.class)
 *  2.手动调用：MockitoAnnotations.initMocks(this);
 *
 * @author 门那粒沙
 * @create 2020-02-03 13:26
 **/
@RunWith(MockitoJUnitRunner.class)
public class MockMvcTest2 {

    private MockMvc mockMvc;

    @Mock
    private MyService myService;

    /**
     * 会注入其他mock对象，例如myService
     */
    @InjectMocks
    private MyController myController;

    @Before
    public void before() {
        // 指定controller，支持多个
        StandaloneMockMvcBuilder mockMvcBuilder = MockMvcBuilders.standaloneSetup(myController)
                .setControllerAdvice(MyExceptionHandler.class) // 无效
                .addFilter(new MyFilter(), "/*") //添加过滤器
                .alwaysExpect(status().isOk()) //配置期望所有响应中的状态为200
                .defaultRequest(post("/").header("token", "test")); // 设置默认请求属性

        // 添加string转date的自定义转换器
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
        conversionService.addConverter(new StringToDateConverter("yyyy-MM-dd"));
        mockMvcBuilder.setConversionService(conversionService);

        mockMvc = mockMvcBuilder.build();

        RequestMappingHandlerMapping handlerMapping = (RequestMappingHandlerMapping) mockMvc.getDispatcherServlet().getHandlerMappings().get(0);
        handlerMapping.setRemoveSemicolonContent(false);    // 放开使用矩阵变量 @MatrixVariable


    }

    /**
     * 测试get请求
     * @throws Exception
     */
    @Test
    public void mockGet() throws Exception {
        String name = "pwd";
        mockMvc.perform(get("/my1/param/{name};id=1,2", name)
                .param("date", "2019-08-01")
                .param("error", "3"))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andExpect(jsonPath("$.name").value("pwd"))
                .andDo(MockMvcResultHandlers.print());
    }


}
